<?php

set_include_path(implode(PATH_SEPARATOR, array(
    realpath('../libraries'),
    get_include_path(),
)));

include_once '../libraries/Zend/Service/Amazon/S3.php';
include_once 'config.php';

//var_dump($argv);

class S3_Uploader
{
	const PRIVACY_PUBLIC = 'public';
	const PRIVACY_PRIVATE = 'private';

	private $_default_meta = array(
		'Cache-Control' => 'public, max-age=2592000'
	);
	private $_s3;
	private $_bucket;
	private $_prefix;

	public function __construct()
	{
		$this->_s3 = new Zend_Service_Amazon_S3(S3_KEY, S3_SECRET);
		$this->_bucket = S3_BUCKET;
		$this->_prefix = $this->_bucket;
	}

	public function put($filename, $data, $privacy = self::PRIVACY_PUBLIC)
	{
		$filename = str_replace("\\", "/", $filename);
		return $this->_s3->putObject($this->_prefix . $filename
						, $data
						, $this->_generateMetaFromPrivacy($privacy, $filename));
	}

	private function _generateMetaFromPrivacy($privacy, $filename)
	{
		$meta = $this->_getDefaultMeta($filename);
		if ($privacy == self::PRIVACY_PUBLIC)
		{
			$meta = array_merge($meta, array(Zend_Service_Amazon_S3::S3_ACL_HEADER =>
				Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ));
		}
		return $meta;
	}

	private function _getDefaultMeta($filename)
	{
		$cache_two_hours = explode('|', CACHE_TWO_HOURS);
		$cache_two_days = explode('|', CACHE_TWO_DAYS);
		$filetype = $this->_getFileType($filename);
		
		if (in_array($filetype, $cache_two_hours))
		{
			return array(
				'Cache-Control' => 'public, max-age=7200'
			);
		}
		else if(in_array($filetype, $cache_two_days))
		{
			return array(
				'Cache-Control' => 'public, max-age=172800'
			);
		}
		else
		{
			return $this->_default_meta;
		}
	}
	
	private function _getFileType($filename)
	{
		return substr($filename, strrpos($filename,'.')+1);
	}

	/**
	 *
	 * @return array() list of parent (..) directories
	 */
	private function getAllParentDir()
	{
		$array_dirs = array();
		$path = '../';
		if ($handle = opendir($path))
		{
			$excluded_folder = explode(',', EXCLUDED_FOLDERS);
			while (false !== ($entry = readdir($handle)))
			{
				if (!in_array($entry, $excluded_folder))
				{
					if (is_dir($path . '/' . $entry))
					{
						$array_dirs[] = $entry;
						echo $entry . PHP_EOL;
					}
				}
			}
			closedir($handle);
		}
		return $array_dirs;
	}

	/**
	 *
	 * @param string $path 
	 */
	public function proccessUpload($path)
	{
		if (is_dir($path))
		{
			$iterator = new RecursiveDirectoryIterator($path);
			foreach (new RecursiveIteratorIterator($iterator) as $file)
			{
				$this->upload($file);
			}
		}
		else
		{
			print "Erorr: There is no public folder in this path" . PHP_EOL;
		}
	}

	public function uploadAll()
	{
		$all_dir = $this->getAllParentDir();
		$path = '../';
		foreach ($all_dir as $dir)
		{
			if (is_dir($path . $dir . '/public'))
			{
				$this->proccessUpload($path . $dir . '/public');
			}
		}
	}
	
	public function uploadChangedFiles($path)
	{
		$files = $this->getArrayChangedFiles($path);
		if (sizeof($files) > 0)
		{
			foreach ($files as $file)
			{
				$this->upload($file);
			}
		}
		else
		{
			echo sprintf('There are no changed files in %s', $path) . PHP_EOL;
		}
	}
	
	public function upload($file)
	{
		$disallowed = explode(',', EXCLUDED_EXTENSIONS);
		if (!strrpos($file, '.svn'))
		{
			if (!in_array(substr($file, strrpos($file, '.') + 1), $disallowed))
			{
				$file = str_replace('\\', '/', $file);
				$data = file_get_contents($file);
				
				if ($this->put(substr($file, 2), $data))
				{
					echo PHP_EOL . 'Success:';
				}
				else
				{
					print PHP_EOL . 'Failed:';
				}
				echo substr($file, 2) . PHP_EOL;
			}
			else
			{
				echo 'This file extension is not allowed to upload!';
			}
		}
	}
	
	private function getArrayChangedFiles($path)
	{
		$arrayFiles = array();
		$data = $this->getSVNStatus($path);
		$lines = explode("\r\n", $data);
		foreach ($lines as $key => $line)
		{
			$status = substr($line, 0, 1);
			$file = substr($line, stripos($line, '..'), strlen($line));
			if (in_array($status, array('M', 'A')))
			{
				$arrayFiles[] = $file;
			}
		}
		return $arrayFiles;
	}
	
	private function getSVNStatus($folder)
	{
		$data = null;
		ob_start();
		passthru(sprintf('svn status %s', $folder));
		$data = ob_get_contents();
		ob_end_clean();
		return $data;
	}
	
	public function handleArgument($args)
	{
		//e.g:php upload-s3.php comics (upload all file with M and A svn status)
		if (sizeof($args) == 2)
		{
			echo 'Uploading changed files in ' . $args[1] . '/public folder to S3' . PHP_EOL;
			$this->uploadChangedFiles(sprintf("../%s/public", $args[1]));
		}
		else if(sizeof($args) == 3)
		{
			//e.g:php upload-s3.php comics full (upload all file with all svn status)
			if ($args[2] == 'full')
			{
				echo 'Uploading ' . $args[1] . '/public folder to S3' . PHP_EOL;
				$this->proccessUpload(sprintf("../%s/public", $args[1]));
			}
			else
			{
				/**
				 *	e.g:
				 * php upload-s3.php comics public/img/payal.png
				 * php upload-s3.php comics public/javscript/
				 */
				$path = sprintf("../%s/%s", $args[1], $args[2]);
				if (is_dir($path))
				{
					echo 'Uploading ' . $path . ' folder to S3' . PHP_EOL;
					$this->proccessUpload($path);
				}
				else
				{
					echo 'Uploading ' . $path . ' to S3' . PHP_EOL;
					$this->upload($path);
				}
			}
		}
	}

}

switch ($argv[1])
{
	case 'all':       
		echo 'Uploading all project/public folder to S3' . PHP_EOL;
		$s3 = new S3_Uploader();
		$s3->uploadAll();
		break;
	default:       
		$s3 = new S3_Uploader();
		$s3->handleArgument($argv);
		break;
}
